﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Configuration;
using System.IO;
using System.Reflection;
using System.Net;

namespace Indigo.Quibbler
{
    internal class Utilities
    {
        #region Enum
        public enum MessageType { Information = 0, Warning, Error };
        public enum LogTargetType { EventLog, File };
        #endregion

        #region Properties: Application Level Settings
        private static string _applicationName = "Universal News Reader";
        public static string ApplicationName
        {
            get { return _applicationName; }
            set { _applicationName = value; }
        }

        private static LogTargetType _logTarget = _GetLogType();
        public static LogTargetType LogTarget
        {
            get { return _logTarget; }
            set { _logTarget = value; }
        }

        private static bool _isEnabled = _GetIsEnabled();
        public static bool IsEnabled
        {
            get { return _isEnabled; }
            set { _isEnabled = value; }
        }

        public static string LogsDirPath
        {
            get { return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"Universal News Reader\Logs\"); }
        }

        public static string DataStorePath
        {
            get { return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"Universal News Reader\DataStore\"); }
        }
        #endregion

        #region Public Methods: Log Exception
        public static void Log(string message)
        {
            Log(message, MessageType.Information);
        }

        public static void Log(string message, Exception ex)
        {
            string errMessage = message;
            while (ex != null)
            {
                errMessage += System.Environment.NewLine + ex.Message +
                            System.Environment.NewLine + ex.StackTrace +
                             System.Environment.NewLine;
                ex = ex.InnerException;
            }

            Log(errMessage, MessageType.Error);
        }

        public static void Log(string message, MessageType messageType)
        {
            if (!Utilities.IsEnabled) return;

            try
            {
                switch (Utilities.LogTarget)
                {
                    case LogTargetType.EventLog: _WriteToEventLog(message, messageType); break;
                    case LogTargetType.File: _WriteToFileLog(message, messageType); break;
                }
            }
            catch { ;}
        }
        #endregion

        #region Public Methods: Get Version
        public static string GetCurrentVersion()
        {
            return Assembly.GetExecutingAssembly().GetName().Version.ToString();
        }
        #endregion

        #region Helper Functions
        private static bool _GetIsEnabled()
        {
            try { return bool.Parse(ConfigurationSettings.AppSettings["Log.Enable"]); }
            catch { }

            return true;
        }

        private static LogTargetType _GetLogType()
        {
            try { return (LogTargetType)Enum.Parse(typeof(LogTargetType), ConfigurationSettings.AppSettings["Log.Target"]); }
            catch { }

            return LogTargetType.File;
        }

        private static void _WriteToEventLog(string message, MessageType messageType)
        {
            string source = Utilities.ApplicationName;
            string log = "Application";
            if (!EventLog.SourceExists(source))
                EventLog.CreateEventSource(source, log);

            switch (messageType)
            {
                case MessageType.Error:
                    EventLog.WriteEntry(source, message, EventLogEntryType.Error);
                    break;
                case MessageType.Warning:
                    EventLog.WriteEntry(source, message, EventLogEntryType.Warning);
                    break;
                case MessageType.Information:
                default:
                    EventLog.WriteEntry(source, message, EventLogEntryType.Information);
                    break;
            }
        }

        private static void _WriteToFileLog(string message, MessageType messageType)
        {
            string logsDir = Utilities.LogsDirPath;
            if (!Directory.Exists(logsDir))
                Directory.CreateDirectory(logsDir);

            string file = Path.GetDirectoryName(logsDir);
            file = Path.Combine(file, Assembly.GetExecutingAssembly().GetName().Name + ".log");
            message = string.Format("\r\n {0}: {1}: {2}", DateTime.Now, messageType, message);
            File.AppendAllText(file, message);
        }
        #endregion
    }

    public class CustomWebClient : WebClient {
        private CookieContainer _cookieContainer;
        private int _timeout;
        private WebResponse _response;
        private WebRequest _request;

        public CustomWebClient() {
            this._cookieContainer = new CookieContainer();
            this.SetTimeout(60 * 1000);
        }

        public CustomWebClient SetTimeout(int timeout) {
            this._timeout = timeout;
            return this;
        }

        public WebResponse Response {
            get { return this._response; }
        }
        
        protected override WebRequest GetWebRequest(Uri address) {
            WebRequest request = base.GetWebRequest(address);

            if (request.GetType() == typeof(HttpWebRequest)) {
                ((HttpWebRequest)request).CookieContainer = this._cookieContainer;
                ((HttpWebRequest)request).Timeout = this._timeout;
            }

            this._request = request;
            return request;
        }

        protected override WebResponse GetWebResponse(WebRequest request) {
            this._response = base.GetWebResponse(request);
            return this._response;
        }

        protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result) {
            this._response = base.GetWebResponse(request, result);
            return this._response;
        }
    } 
}
